package com.sugar.real.estate.module.business.service.user;

import cn.hutool.core.util.StrUtil;
import com.sugar.real.estate.framework.common.pojo.PageResult;
import com.sugar.real.estate.framework.common.util.object.BeanUtils;
import com.sugar.real.estate.module.business.controller.admin.user.vo.BizUserPageReqVO;
import com.sugar.real.estate.module.business.controller.admin.user.vo.BizUserSaveReqVO;
import com.sugar.real.estate.module.business.controller.app.user.vo.AppBizUserLoginReqVO;
import com.sugar.real.estate.module.business.controller.app.user.vo.AppBizUserRespVO;
import com.sugar.real.estate.module.business.controller.app.user.vo.AppBizUserUpdateReqVO;
import com.sugar.real.estate.module.business.dal.dataobject.user.BizUserDO;
import com.sugar.real.estate.module.business.dal.mysql.user.BizUserMapper;
import com.sugar.real.estate.module.business.enums.config.ConfigEnum;
import com.sugar.real.estate.module.business.service.config.BizConfigService;
import com.sugar.real.estate.module.business.util.I18nUtil;
import com.sugar.real.estate.module.business.util.wechat.WeChatLoginUtil;
import com.sugar.real.estate.module.system.api.auth.AuthApi;
import com.sugar.real.estate.module.system.api.auth.dto.AppAuthDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;

import static com.sugar.real.estate.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.sugar.real.estate.module.business.enums.ErrorCodeConstants.*;

/**
 * 用户 Service 实现类
 *
 * @author Ysugar
 */
@Slf4j
@Service
@Validated
public class BizUserServiceImpl implements BizUserService {

    @Resource
    private BizUserMapper bizUserMapper;
    @Resource
    private BizConfigService configService;
    @Resource
    private AuthApi authApi;

    private static final ReentrantLock LOGIN_LOCK = new ReentrantLock();

    @Override
    public Long createBizUser(BizUserSaveReqVO createReqVO) {
        // 插入
        BizUserDO bizUser = BeanUtils.toBean(createReqVO, BizUserDO.class);
        bizUserMapper.insert(bizUser);
        // 返回
        return bizUser.getId();
    }

    @Override
    public void updateBizUser(BizUserSaveReqVO updateReqVO) {
        // 校验存在
        validateBizUserExists(updateReqVO.getId());
        // 更新
        BizUserDO updateObj = BeanUtils.toBean(updateReqVO, BizUserDO.class);
        bizUserMapper.updateById(updateObj);
    }

    @Override
    public void deleteBizUser(Long id) {
        // 校验存在
        validateBizUserExists(id);
        // 删除
        bizUserMapper.deleteById(id);
    }

    private void validateBizUserExists(Long id) {
        if (bizUserMapper.selectById(id) == null) {
            throw exception(BIZ_USER_NOT_EXISTS);
        }
    }

    @Override
    public BizUserDO getBizUser(Long id) {
        return bizUserMapper.selectById(id);
    }

    @Override
    public PageResult<BizUserDO> getBizUserPage(BizUserPageReqVO pageReqVO) {
        return bizUserMapper.selectPage(pageReqVO);
    }

    // ======================================== APP 接口 ========================================

    @Override
    public AppAuthDTO login(AppBizUserLoginReqVO loginReqVO) {
        // 根据手机号code换取手机号
        String userMobile = WeChatLoginUtil.getUserMobile(loginReqVO.getMobileCode());
        if (StrUtil.isBlank(userMobile))
            throw exception(WE_CHAT_MOBILE_AUTH_ERROR, I18nUtil.getMessage("WE_CHAT_MOBILE_AUTH_ERROR"));

        // 根据 手机号 查询用户信息
        BizUserDO user = bizUserMapper.selectOne(BizUserDO::getMobile, userMobile);

        if (Objects.isNull(user)) {
            LOGIN_LOCK.lock();
            try {
                // 再次查询
                user = bizUserMapper.selectOne(BizUserDO::getMobile, userMobile);
                if (Objects.isNull(user)) {
                    // 获取默认头像
                    String avatar = configService.getBizConfigByKey(ConfigEnum.USER_DEFAULT_AVATAR, String.class);

                    user = new BizUserDO();
                    user.setMobile(userMobile)
                            .setNickname(userMobile)
                            // 设置默认头像
                            .setAvatar(avatar)
                            .setLastLoginTime(LocalDateTime.now());

                    if (bizUserMapper.insert(user) <= 0)
                        throw exception(BIZ_USER_REGISTER_ERROR, I18nUtil.getMessage("BIZ_USER_REGISTER_ERROR"));
                }
            } catch (Throwable e) {
                log.error("用户注册失败：", e);
            } finally {
                if (LOGIN_LOCK.isLocked())
                    LOGIN_LOCK.unlock();
            }
        } else if (!user.getStatus())
            throw exception(USER_ACCOUNT_FORBIDDEN);
        else
            // 更新用户最后一次登录时间
            bizUserMapper.update(BizUserDO::getId, user.getId(), BizUserDO::getLastLoginTime, LocalDateTime.now());

        AppAuthDTO appAuthDTO = authApi.appLogin(user.getId(), user.getMobile());

        appAuthDTO.setUserInfo(BeanUtils.toBean(user, AppBizUserRespVO.class));
        return appAuthDTO;
    }

    @Override
    public void appUpdateBizUser(AppBizUserUpdateReqVO updateReqVO, Long userId) {
        String avatar = updateReqVO.getAvatar();
        String nickname = updateReqVO.getNickname();

        if (StrUtil.isNotBlank(avatar) || StrUtil.isNotBlank(nickname))
            bizUserMapper.update(BizUserDO::getId, userId, BizUserDO::getAvatar, avatar, BizUserDO::getNickname, nickname);
    }
}